<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>🌙 垃圾回收机制 | Xiangyu&#39;s Blog</title>
    <meta name="generator" content="VuePress 1.8.2">
    <script src="https://cdn.jsdelivr.net/npm/react/umd/react.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/react-dom/umd/react-dom.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@babel/standalone/babel.min.js"></script>
    <link rel="alternate" type="application/atom+xml" href="https://blog.lixiangyu.xyz/atom.xml" title="Xiangyu&#39;s Blog Atom Feed">
    <link rel="alternate" type="application/json" href="https://blog.lixiangyu.xyz/feed.json" title="Xiangyu&#39;s Blog JSON Feed">
    <link rel="alternate" type="application/rss+xml" href="https://blog.lixiangyu.xyz/rss.xml" title="Xiangyu&#39;s Blog RSS Feed">
    <meta name="description" content="">
    <meta property="og:url" content="/interview/jvm/gc.html">
    <meta property="og:site_name" content="Xiangyu's Blog">
    <meta property="og:title" content="🌙 垃圾回收机制">
    <meta property="og:type" content="article">
    <meta property="og:locale" content="zh-CN">
    <meta name="twitter:card" content="summary_large_image">
    <meta name="twitter:image:alt" content="Xiangyu's Blog">
    <meta property="article:author" content="Xiangyu Li">
    
    <link rel="preload" href="/assets/css/0.styles.79654418.css" as="style"><link rel="preload" href="/assets/js/app.a42375e9.js" as="script"><link rel="preload" href="/assets/js/vendors~layout-Layout.8269724e.js" as="script"><link rel="preload" href="/assets/js/vendors~layout-Blog~layout-Layout~layout-NotFound.43b0f70d.js" as="script"><link rel="preload" href="/assets/js/page-🌙垃圾回收机制.db23d79a.js" as="script"><link rel="preload" href="/assets/js/vendors~layout-Blog~layout-Layout~layout-NotFound~layout-Slide.99c28334.js" as="script"><link rel="prefetch" href="/assets/js/120.3fbfaa84.js"><link rel="prefetch" href="/assets/js/121.1b7d4f7b.js"><link rel="prefetch" href="/assets/js/122.beff33c9.js"><link rel="prefetch" href="/assets/js/123.b1ea2b2a.js"><link rel="prefetch" href="/assets/js/124.80db1ca6.js"><link rel="prefetch" href="/assets/js/layout-Blog.5897b816.js"><link rel="prefetch" href="/assets/js/layout-Layout.62afd99c.js"><link rel="prefetch" href="/assets/js/layout-NotFound.232bd0de.js"><link rel="prefetch" href="/assets/js/layout-Slide.3e86b53c.js"><link rel="prefetch" href="/assets/js/mermaid.efa5ef99.js"><link rel="prefetch" href="/assets/js/page-☀️类加载机制.e96f671b.js"><link rel="prefetch" href="/assets/js/page-☘️通讯组件-简介.4b81f185.js"><link rel="prefetch" href="/assets/js/page-♟️百度.c4749d47.js"><link rel="prefetch" href="/assets/js/page-⛈️Map接口-简介.3865d2e3.js"><link rel="prefetch" href="/assets/js/page-⛑️HTTPS协议.66168577.js"><link rel="prefetch" href="/assets/js/page-⛷️TreeSet.9d82d551.js"><link rel="prefetch" href="/assets/js/page-⛹️LinkedHashMap.a11fa0e5.js"><link rel="prefetch" href="/assets/js/page-✈️Kafka.02647d0b.js"><link rel="prefetch" href="/assets/js/page-✌️索引.8092b72a.js"><link rel="prefetch" href="/assets/js/page-⭐内存区域划分.b3f4a65e.js"><link rel="prefetch" href="/assets/js/page-主页.28a585f2.js"><link rel="prefetch" href="/assets/js/page-🌀JVM-简介.cbd691d7.js"><link rel="prefetch" href="/assets/js/page-🌀JavaIO-简介.8b218ef6.js"><link rel="prefetch" href="/assets/js/page-🌀Java基础-简介.3cff2536.js"><link rel="prefetch" href="/assets/js/page-🌀Java容器-简介.21a7bf8b.js"><link rel="prefetch" href="/assets/js/page-🌀Java并发-简介.a400b8d1.js"><link rel="prefetch" href="/assets/js/page-🌀MySQL-简介.61b33b6a.js"><link rel="prefetch" href="/assets/js/page-🌀Redis-简介.f815bad6.js"><link rel="prefetch" href="/assets/js/page-🌀中间件-简介.5640181c.js"><link rel="prefetch" href="/assets/js/page-🌀操作系统-简介.46e7356e.js"><link rel="prefetch" href="/assets/js/page-🌀框架使用-简介.3af4c120.js"><link rel="prefetch" href="/assets/js/page-🌀计算机网络-简介.23bd59fd.js"><link rel="prefetch" href="/assets/js/page-🌀设计思想-简介.0711e244.js"><link rel="prefetch" href="/assets/js/page-🌀面经.5cfe0142.js"><link rel="prefetch" href="/assets/js/page-🌧️Set接口-简介.d19cf767.js"><link rel="prefetch" href="/assets/js/page-🌩️List接口-简介.112f20b7.js"><link rel="prefetch" href="/assets/js/page-🌲Spring.bc450c2f.js"><link rel="prefetch" href="/assets/js/page-🌳SpringMVC.91b7e35a.js"><link rel="prefetch" href="/assets/js/page-🌴SpringBoot.ff4435cc.js"><link rel="prefetch" href="/assets/js/page-🌵SpringCloud.61f20500.js"><link rel="prefetch" href="/assets/js/page-🌻MyBatis.2d99e7fc.js"><link rel="prefetch" href="/assets/js/page-🌼MyBatis框架-简介.66f9a744.js"><link rel="prefetch" href="/assets/js/page-🍀Netty.54e2d65a.js"><link rel="prefetch" href="/assets/js/page-🍁Dubbo.66727d8a.js"><link rel="prefetch" href="/assets/js/page-🎧学堂在线.81d9ee7e.js"><link rel="prefetch" href="/assets/js/page-🎭Boss直聘.14beba08.js"><link rel="prefetch" href="/assets/js/page-🎱老虎集团.fc8b12ba.js"><link rel="prefetch" href="/assets/js/page-🎲字节跳动.5676ea28.js"><link rel="prefetch" href="/assets/js/page-🎺猿辅导.7520f1e7.js"><link rel="prefetch" href="/assets/js/page-🏄LinkedHashSet.2e22c9f1.js"><link rel="prefetch" href="/assets/js/page-🏌️HashSet.820baa69.js"><link rel="prefetch" href="/assets/js/page-🐒锁.868714d5.js"><link rel="prefetch" href="/assets/js/page-🐵JUC.9672a0f1.js"><link rel="prefetch" href="/assets/js/page-👂视图.f277e783.js"><link rel="prefetch" href="/assets/js/page-👋数据类型.b99f167f.js"><link rel="prefetch" href="/assets/js/page-👍事务.ef00d241.js"><link rel="prefetch" href="/assets/js/page-👎慢查询.a1afcd91.js"><link rel="prefetch" href="/assets/js/page-👓IP地址.f0579df2.js"><link rel="prefetch" href="/assets/js/page-👕其他.647a9b2f.js"><link rel="prefetch" href="/assets/js/page-👟滑动窗口.b3cb4c10.js"><link rel="prefetch" href="/assets/js/page-👣IP协议基础.c423881a.js"><link rel="prefetch" href="/assets/js/page-👨‍💼TCP协议-简介.8dad7177.js"><link rel="prefetch" href="/assets/js/page-👨‍🔧IP-简介.45549536.js"><link rel="prefetch" href="/assets/js/page-👨‍🔧设计模式.2b288cfc.js"><link rel="prefetch" href="/assets/js/page-💁‍♂️Redis事务.2da37f16.js"><link rel="prefetch" href="/assets/js/page-💂面试知识点整理.53653cc8.js"><link rel="prefetch" href="/assets/js/page-💍HTTP协议的改进.9d91d303.js"><link rel="prefetch" href="/assets/js/page-💐Spring全家桶-简介.bc0ceb52.js"><link rel="prefetch" href="/assets/js/page-💼HTTP协议的请求方法.49ea5b30.js"><link rel="prefetch" href="/assets/js/page-🖐️存储引擎.51e90aae.js"><link rel="prefetch" href="/assets/js/page-🖖DDL.58e99d50.js"><link rel="prefetch" href="/assets/js/page-😀面向对象的特点.64db987a.js"><link rel="prefetch" href="/assets/js/page-😁Object类.bd3dee32.js"><link rel="prefetch" href="/assets/js/page-😆String类.6fe32326.js"><link rel="prefetch" href="/assets/js/page-😎泛型.9245d81a.js"><link rel="prefetch" href="/assets/js/page-😛关键字.1e781f13.js"><link rel="prefetch" href="/assets/js/page-😪反射.ef7a385f.js"><link rel="prefetch" href="/assets/js/page-😵异常.6c2ba11a.js"><link rel="prefetch" href="/assets/js/page-🙅‍♂️Redis淘汰策略.650f7bea.js"><link rel="prefetch" href="/assets/js/page-🙆‍♂️Redis持久化策略.d130b1b1.js"><link rel="prefetch" href="/assets/js/page-🙇‍♂️Redis基础.2c3c39e8.js"><link rel="prefetch" href="/assets/js/page-🙈JMM.3512b22b.js"><link rel="prefetch" href="/assets/js/page-🙉进程和线程.f7aa9975.js"><link rel="prefetch" href="/assets/js/page-🙊线程池.bab2c4d8.js"><link rel="prefetch" href="/assets/js/page-🙋‍♂️Redis底层实现.7416ea6f.js"><link rel="prefetch" href="/assets/js/page-🚥ZooKeeper.57458d21.js"><link rel="prefetch" href="/assets/js/page-🚵HashTable.ccce702b.js"><link rel="prefetch" href="/assets/js/page-🚶‍♂️超时重传机制.cfb21e2f.js"><link rel="prefetch" href="/assets/js/page-🤚范式.b6a8d503.js"><link rel="prefetch" href="/assets/js/page-🤝集群.bdd1180d.js"><link rel="prefetch" href="/assets/js/page-🤞锁.c12200cd.js"><link rel="prefetch" href="/assets/js/page-🤦‍♂️故障处理.80248294.js"><link rel="prefetch" href="/assets/js/page-🤪包装类和缓存池.4fa40654.js"><link rel="prefetch" href="/assets/js/page-🤴HTTP协议-简介.c55283d9.js"><link rel="prefetch" href="/assets/js/page-🤸ArrayList.f0cf8991.js"><link rel="prefetch" href="/assets/js/page-🤹LinkedList.caf8cd71.js"><link rel="prefetch" href="/assets/js/page-🤼HashMap.2ad7d223.js"><link rel="prefetch" href="/assets/js/page-🤾Vector.7740cb05.js"><link rel="prefetch" href="/assets/js/page-🥁好大夫在线.e46779d8.js"><link rel="prefetch" href="/assets/js/page-🦍无同步方案.9b8df198.js"><link rel="prefetch" href="/assets/js/page-🧏‍♂️Redis集群.6d3441ab.js"><link rel="prefetch" href="/assets/js/page-🧐其他.deb18f3f.js"><link rel="prefetch" href="/assets/js/page-🧘ConcurrentHashMap.a3e51c7d.js"><link rel="prefetch" href="/assets/js/page-🧙‍♂️内存管理.c1b418f2.js"><link rel="prefetch" href="/assets/js/page-🧚CPU缓存一致性.8647e92e.js"><link rel="prefetch" href="/assets/js/page-🧛‍♂️IO.3bf30d07.js"><link rel="prefetch" href="/assets/js/page-🧝‍♂️进程与线程.f1df829e.js"><link rel="prefetch" href="/assets/js/page-🧟锁.86b4ff29.js"><link rel="prefetch" href="/assets/js/page-🧣TCP协议基础.2e717ff6.js"><link rel="prefetch" href="/assets/js/page-🧤拥塞控制.9018c6ff.js"><link rel="prefetch" href="/assets/js/page-🧥HTTP协议基础.719b302d.js"><link rel="prefetch" href="/assets/js/page-🧩美团.7049187d.js"><link rel="prefetch" href="/assets/js/page-🧳建立与释放连接.b95bfaf5.js"><link rel="prefetch" href="/assets/js/page-🧶元保数科.aba682de.js"><link rel="prefetch" href="/assets/js/vendors~flowchart.846214db.js"><link rel="prefetch" href="/assets/js/vendors~mermaid.4a0cbbd3.js"><link rel="prefetch" href="/assets/js/vendors~photo-swipe.515ad438.js"><link rel="prefetch" href="/assets/js/vendors~reveal.b4fb0aa4.js"><link rel="prefetch" href="/assets/js/vendors~waline.c2d7e472.js">
    <link rel="stylesheet" href="/assets/css/0.styles.79654418.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container has-navbar has-sidebar has-anchor"><header class="navbar"><!----> <div class="content__navbar-start"></div> <button title="Sidebar Button" class="sidebar-button"><span class="icon"></span></button> <a href="/" class="home-link router-link-active"><img src="/icon.png" alt="Xiangyu's Blog" class="logo"> <!----> <span class="site-name can-hide">Xiangyu's Blog</span></a> <!----> <div class="content__navbar-center"></div> <div class="links"><button aria-hidden="true" class="color-button"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="skin-icon"><path d="M224 800c0 9.6 3.2 44.8 6.4 54.4 6.4 48-48 76.8-48 76.8s80 41.6 147.2 0 134.4-134.4
        38.4-195.2c-22.4-12.8-41.6-19.2-57.6-19.2C259.2 716.8 227.2 761.6 224 800zM560 675.2l-32
        51.2c-51.2 51.2-83.2 32-83.2 32 25.6 67.2 0 112-12.8 128 25.6 6.4 51.2 9.6 80 9.6 54.4 0
        102.4-9.6 150.4-32l0 0c3.2 0 3.2-3.2 3.2-3.2 22.4-16 12.8-35.2
        6.4-44.8-9.6-12.8-12.8-25.6-12.8-41.6 0-54.4 60.8-99.2 137.6-99.2 6.4 0 12.8 0 22.4
        0 12.8 0 38.4 9.6 48-25.6 0-3.2 0-3.2 3.2-6.4 0-3.2 3.2-6.4 3.2-6.4 6.4-16 6.4-16 6.4-19.2
        9.6-35.2 16-73.6 16-115.2 0-105.6-41.6-198.4-108.8-268.8C704 396.8 560 675.2 560 675.2zM224
        419.2c0-28.8 22.4-51.2 51.2-51.2 28.8 0 51.2 22.4 51.2 51.2 0 28.8-22.4 51.2-51.2 51.2C246.4
        470.4 224 448 224 419.2zM320 284.8c0-22.4 19.2-41.6 41.6-41.6 22.4 0 41.6 19.2 41.6 41.6 0
        22.4-19.2 41.6-41.6 41.6C339.2 326.4 320 307.2 320 284.8zM457.6 208c0-12.8 12.8-25.6 25.6-25.6
        12.8 0 25.6 12.8 25.6 25.6 0 12.8-12.8 25.6-25.6 25.6C470.4 233.6 457.6 220.8 457.6 208zM128
        505.6C128 592 153.6 672 201.6 736c28.8-60.8 112-60.8 124.8-60.8-16-51.2 16-99.2
        16-99.2l316.8-422.4c-48-19.2-99.2-32-150.4-32C297.6 118.4 128 291.2 128 505.6zM764.8
        86.4c-22.4 19.2-390.4 518.4-390.4 518.4-22.4 28.8-12.8 76.8 22.4 99.2l9.6 6.4c35.2 22.4
        80 12.8 99.2-25.6 0 0 6.4-12.8 9.6-19.2 54.4-105.6 275.2-524.8 288-553.6
        6.4-19.2-3.2-32-19.2-32C777.6 76.8 771.2 80 764.8 86.4z"></path></svg> <div class="color-picker-menu" style="display:none;"><div class="theme-options"><ul class="themecolor-select"><label for="themecolor-select">主题色:</label> <li><span class="default-theme"></span></li> </ul> <div class="darkmode-toggle"><label for="darkmode-toggle" class="desc">主题模式:</label> <div class="darkmode-switch"><div class="item day"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="icon light-icon"><path d="M512 256a42.667 42.667 0 0 0 42.667-42.667V128a42.667 42.667 0 0 0-85.334 0v85.333A42.667 42.667 0 0 0 512 256zm384 213.333h-85.333a42.667 42.667 0 0 0 0 85.334H896a42.667 42.667 0 0 0 0-85.334zM256 512a42.667 42.667 0 0 0-42.667-42.667H128a42.667 42.667 0 0 0 0 85.334h85.333A42.667 42.667 0 0 0 256 512zm9.387-298.667a42.667 42.667 0 0 0-59.307 62.72l61.44 59.307a42.667 42.667 0 0 0 31.147 11.947 42.667 42.667 0 0 0 30.72-13.227 42.667 42.667 0 0 0 0-60.16zm459.946 133.974a42.667 42.667 0 0 0 29.44-11.947l61.44-59.307a42.667 42.667 0 0 0-57.6-62.72l-61.44 60.587a42.667 42.667 0 0 0 0 60.16 42.667 42.667 0 0 0 28.16 13.227zM512 768a42.667 42.667 0 0 0-42.667 42.667V896a42.667 42.667 0 0 0 85.334 0v-85.333A42.667 42.667 0 0 0 512 768zm244.48-79.36a42.667 42.667 0 0 0-59.307 61.44l61.44 60.587a42.667 42.667 0 0 0 29.44 11.946 42.667 42.667 0 0 0 30.72-12.8 42.667 42.667 0 0 0 0-60.586zm-488.96 0-61.44 59.307a42.667 42.667 0 0 0 0 60.586 42.667 42.667 0 0 0 30.72 12.8 42.667 42.667 0 0 0 28.587-10.666l61.44-59.307a42.667 42.667 0 0 0-59.307-61.44zM512 341.333A170.667 170.667 0 1 0 682.667 512 170.667 170.667 0 0 0 512 341.333z" fill="currentColor"></path></svg></div> <div class="item auto active"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="icon auto-icon"><path d="M460.864 539.072H564.8L510.592 376l-49.728 163.072zM872 362.368V149.504H659.648L510.528 0l-149.12 149.504H149.12v212.928L0 511.872l149.12 149.504v212.928h212.352l149.12 149.504 149.12-149.504h212.352V661.376l149.12-149.504L872 362.368zM614.464 693.12l-31.616-90.624H438.272l-31.616 90.624h-85.888l144.576-407.68h90.368l144.576 407.68h-85.824zm0 0" fill="currentColor"></path></svg></div> <div class="item night"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="icon dark-icon"><path d="M935.539 630.402c-11.43-11.432-28.674-14.739-43.531-8.354-46.734 20.103-96.363 30.297-147.508 30.297-99.59 0-193.221-38.784-263.64-109.203-108.637-108.637-139.61-270.022-78.908-411.148a39.497 39.497 0 0 0-51.886-51.887c-52.637 22.64-100.017 54.81-140.826 95.616-85.346 85.346-132.346 198.821-132.346 319.52 0 120.7 47.001 234.172 132.347 319.519S408.063 947.11 528.76 947.11c120.7 0 234.172-47.003 319.52-132.351 40.809-40.81 72.978-88.19 95.616-140.826a39.497 39.497 0 0 0-8.356-43.532z" fill="currentColor"></path></svg></div></div> <!----></div></div></div></button> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/" class="nav-link router-link-active"><i class="iconfont icon-home"></i>
  主页
</a></div><div class="nav-item"><a href="/interview/" class="nav-link router-link-active active"><i class="iconfont icon-launch"></i>
  面试题整理
</a></div></nav> <!----> <a rel="noopener noreferrer" href="https://github.com/lxy1152/lxy1152.github.io" target="_blank" class="repo-link can-hide">
  GitHub
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> <!----> <div class="content__navbar-end"></div></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><!----> <!----> <div class="content__sidebar-top"></div> <nav class="sidebar-nav-links"><div class="nav-item"><a href="/" class="nav-link router-link-active"><i class="iconfont icon-home"></i>
  主页
</a></div><div class="nav-item"><a href="/interview/" class="nav-link router-link-active active"><i class="iconfont icon-launch"></i>
  面试题整理
</a></div> <a rel="noopener noreferrer" href="https://github.com/lxy1152/lxy1152.github.io" target="_blank" class="repo-link">
  GitHub
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <!----> <div class="content__sidebar-center"></div> <ul class="sidebar-links"><li><a href="/interview/" aria-current="page" class="sidebar-link">💂 面试知识点整理</a></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading clickable"><!----> <span class="title">😉 Java 基础</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading clickable"><!----> <span class="title">🌈 Java 容器</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading clickable"><!----> <span class="title">🐺 Java 并发</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading clickable"><!----> <span class="title">⛳ Java I/O</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading clickable open"><!----> <span class="title">🌏 JVM</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/interview/jvm/" aria-current="page" class="sidebar-link">🌀 JVM - 简介</a></li><li><a href="/interview/jvm/memory-partition/" class="sidebar-link">⭐ 内存区域划分</a></li><li><a href="/interview/jvm/classloader/" class="sidebar-link">☀️ 类加载机制</a></li><li><a href="/interview/jvm/gc/" aria-current="page" class="active sidebar-link">🌙 垃圾回收机制</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/interview/jvm/gc/#对象引用与回收" class="sidebar-link">对象引用与回收</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/interview/jvm/gc/#有哪几种引用类型" class="sidebar-link heading3">有哪几种引用类型？</a></li><li class="sidebar-sub-header"><a href="/interview/jvm/gc/#如何判断对象是否可被回收" class="sidebar-link heading3">如何判断对象是否可被回收？</a></li><li class="sidebar-sub-header"><a href="/interview/jvm/gc/#什么是引用计数算法" class="sidebar-link heading3">什么是引用计数算法？</a></li><li class="sidebar-sub-header"><a href="/interview/jvm/gc/#什么是可达性分析算法" class="sidebar-link heading3">什么是可达性分析算法？</a></li><li class="sidebar-sub-header"><a href="/interview/jvm/gc/#如何判断一个类是否是无用的类" class="sidebar-link heading3">如何判断一个类是否是无用的类？</a></li></ul></li><li class="sidebar-sub-header"><a href="/interview/jvm/gc/#内存分配与回收策略" class="sidebar-link">内存分配与回收策略</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/interview/jvm/gc/#什么是-minor-gc-和-full-gc" class="sidebar-link heading3">什么是 Minor GC 和 Full GC？</a></li><li class="sidebar-sub-header"><a href="/interview/jvm/gc/#jvm-的内存分配策略是什么" class="sidebar-link heading3">JVM 的内存分配策略是什么？</a></li></ul></li><li class="sidebar-sub-header"><a href="/interview/jvm/gc/#垃圾回收算法" class="sidebar-link">垃圾回收算法</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/interview/jvm/gc/#什么是标记-清除算法" class="sidebar-link heading3">什么是标记-清除算法？</a></li><li class="sidebar-sub-header"><a href="/interview/jvm/gc/#什么是标记-整理算法" class="sidebar-link heading3">什么是标记-整理算法？</a></li><li class="sidebar-sub-header"><a href="/interview/jvm/gc/#什么是复制算法" class="sidebar-link heading3">什么是复制算法？</a></li><li class="sidebar-sub-header"><a href="/interview/jvm/gc/#什么是分代收集" class="sidebar-link heading3">什么是分代收集？</a></li></ul></li><li class="sidebar-sub-header"><a href="/interview/jvm/gc/#垃圾回收器" class="sidebar-link">垃圾回收器</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/interview/jvm/gc/#jvm-有哪些垃圾回收器" class="sidebar-link heading3">JVM 有哪些垃圾回收器？</a></li><li class="sidebar-sub-header"><a href="/interview/jvm/gc/#什么是-serial-收集器" class="sidebar-link heading3">什么是 Serial 收集器？</a></li><li class="sidebar-sub-header"><a href="/interview/jvm/gc/#什么是-parnew-收集器" class="sidebar-link heading3">什么是 ParNew 收集器？</a></li><li class="sidebar-sub-header"><a href="/interview/jvm/gc/#什么是-parallel-scavenge-收集器" class="sidebar-link heading3">什么是 Parallel Scavenge 收集器？</a></li><li class="sidebar-sub-header"><a href="/interview/jvm/gc/#什么是-cms-收集器" class="sidebar-link heading3">什么是 CMS 收集器？</a></li><li class="sidebar-sub-header"><a href="/interview/jvm/gc/#什么是-serial-old-收集器" class="sidebar-link heading3">什么是 Serial Old 收集器？</a></li><li class="sidebar-sub-header"><a href="/interview/jvm/gc/#什么是-parallel-old-收集器" class="sidebar-link heading3">什么是 Parallel Old 收集器？</a></li><li class="sidebar-sub-header"><a href="/interview/jvm/gc/#什么是-g1-收集器" class="sidebar-link heading3">什么是 G1 收集器？</a></li></ul></li></ul></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading clickable"><!----> <span class="title">🌱 框架使用</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading clickable"><!----> <span class="title">👊 MySQL</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading clickable"><!----> <span class="title">🤷‍♂️ Redis</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading clickable"><!----> <span class="title">🎠 中间件</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading clickable"><!----> <span class="title">👨‍👧‍👧 计算机网络</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading clickable"><!----> <span class="title">🦸 操作系统</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading clickable"><!----> <span class="title">🏭 设计思想</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading clickable"><!----> <span class="title">📚 面经</span> <span class="arrow right"></span></p> <!----></section></li></ul> <!----> <div class="content__sidebar-bottom"></div> <!----></aside> <main class="page"><nav class="breadcrumb"><ol vocab="https://schema.org/" typeof="BreadcrumbList"><li property="itemListElement" typeof="ListItem"><a href="/interview/" property="item" typeof="WebPage" class="router-link-active"><!----> <span property="name">💂 面试知识点整理</span></a> <meta property="position" content="1"></li><li property="itemListElement" typeof="ListItem"><a href="/interview/jvm/" property="item" typeof="WebPage" class="router-link-active"><!----> <span property="name">🌀 JVM - 简介</span></a> <meta property="position" content="2"></li><li property="itemListElement" typeof="ListItem" class="is-active"><a href="/interview/jvm/gc/" aria-current="page" property="item" typeof="WebPage" class="router-link-exact-active router-link-active"><!----> <span property="name">🌙 垃圾回收机制</span></a> <meta property="position" content="3"></li></ol></nav> <!----> <div class="content__page-top"></div> <div vocab="https://schema.org/" typeof="Article" class="page-title"><h1><!----> <span property="headline">🌙 垃圾回收机制</span></h1> <div class="page-info"><!----> <span aria-label="作者🖊" data-balloon-pos="down"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="icon author-icon"><path d="M649.6 633.6c86.4-48 147.2-144 147.2-249.6 0-160-128-288-288-288s-288 128-288 288c0 108.8 57.6 201.6 147.2 249.6-121.6 48-214.4 153.6-240 288-3.2 9.6 0 19.2 6.4 25.6 3.2 9.6 12.8 12.8 22.4 12.8h704c9.6 0 19.2-3.2 25.6-12.8 6.4-6.4 9.6-16 6.4-25.6-25.6-134.4-121.6-240-243.2-288z" fill="currentColor"></path></svg> <span property="author">Xiangyu Li</span></span><span aria-label="访问量🔢" data-balloon-pos="down" class="visitor-info"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="icon eye-icon"><path d="M992 512.096c0-5.76-.992-10.592-1.28-11.136-.192-2.88-1.152-8.064-2.08-10.816-.256-.672-.544-1.376-.832-2.08-.48-1.568-1.024-3.104-1.6-4.32C897.664 290.112 707.104 160 512 160c-195.072 0-385.632 130.016-473.76 322.592-1.056 2.112-1.792 4.096-2.272 5.856a55.512 55.512 0 0 0-.64 1.6c-1.76 5.088-1.792 8.64-1.632 7.744-.832 3.744-1.568 11.168-1.568 11.168-.224 2.272-.224 4.032.032 6.304 0 0 .736 6.464 1.088 7.808.128 1.824.576 4.512 1.12 6.976h-.032c.448 2.08 1.12 4.096 1.984 6.08.48 1.536.992 2.976 1.472 4.032C126.432 733.856 316.992 864 512 864c195.136 0 385.696-130.048 473.216-321.696 1.376-2.496 2.24-4.832 2.848-6.912.256-.608.48-1.184.672-1.728 1.536-4.48 1.856-8.32 1.728-8.32l-.032.032c.608-3.104 1.568-7.744 1.568-13.28zM512 672c-88.224 0-160-71.776-160-160s71.776-160 160-160 160 71.776 160 160-71.776 160-160 160z" fill="currentColor"></path></svg> <span id="/interview/jvm/gc/" data-flag-title="🌙 垃圾回收机制" class="leancloud_visitors"><span class="leancloud-visitors-count">...</span></span></span><span aria-label="写作日期📅" data-balloon-pos="down" class="time-info"><svg viewBox="0 0 1030 1024" xmlns="http://www.w3.org/2000/svg" class="icon calendar-icon"><path d="M716.4 110.137c0-18.753-14.72-33.473-33.472-33.473-18.753 0-33.473 14.72-33.473 33.473v33.473h66.993v-33.473zm-334.87 0c0-18.753-14.72-33.473-33.473-33.473s-33.52 14.72-33.52 33.473v33.473h66.993v-33.473zm468.81 33.52H716.4v100.465c0 18.753-14.72 33.473-33.472 33.473a33.145 33.145 0 0 1-33.473-33.473V143.657H381.53v100.465c0 18.753-14.72 33.473-33.473 33.473a33.145 33.145 0 0 1-33.473-33.473V143.657H180.6A134.314 134.314 0 0 0 46.66 277.595v535.756A134.314 134.314 0 0 0 180.6 947.289h669.74a134.36 134.36 0 0 0 133.94-133.938V277.595a134.314 134.314 0 0 0-133.94-133.938zm33.473 267.877H147.126a33.145 33.145 0 0 1-33.473-33.473c0-18.752 14.72-33.473 33.473-33.473h736.687c18.752 0 33.472 14.72 33.472 33.473a33.145 33.145 0 0 1-33.472 33.473z" fill="currentColor"></path></svg> <span property="datePublished">2021-8-1</span></span><!----><!----><span aria-label="阅读时间⌛" data-balloon-pos="down" class="reading-time-info"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="icon timer-icon"><path d="M799.387 122.15c4.402-2.978 7.38-7.897 7.38-13.463v-1.165c0-8.933-7.38-16.312-16.312-16.312H256.33c-8.933 0-16.311 7.38-16.311 16.312v1.165c0 5.825 2.977 10.874 7.637 13.592 4.143 194.44 97.22 354.963 220.201 392.763-122.204 37.542-214.893 196.511-220.2 389.397-4.661 5.049-7.638 11.651-7.638 19.03v5.825h566.49v-5.825c0-7.379-2.849-13.981-7.509-18.9-5.049-193.016-97.867-351.985-220.2-389.527 123.24-37.67 216.446-198.453 220.588-392.892zM531.16 450.445v352.632c117.674 1.553 211.787 40.778 211.787 88.676H304.097c0-48.286 95.149-87.382 213.728-88.676V450.445c-93.077-3.107-167.901-81.297-167.901-177.093 0-8.803 6.99-15.793 15.793-15.793 8.803 0 15.794 6.99 15.794 15.793 0 80.261 63.69 145.635 142.01 145.635s142.011-65.374 142.011-145.635c0-8.803 6.99-15.793 15.794-15.793s15.793 6.99 15.793 15.793c0 95.019-73.789 172.82-165.96 177.093z" fill="currentColor"></path></svg> <span>大约 17 分钟</span> <meta property="timeRequired" content="PT17M"></span></div> <!----> <hr></div> <div class="anchor-place-holder"><aside id="anchor"><div class="anchor-wrapper"><ul class="anchor-list"><li class="anchor"><a href="/interview/jvm/gc/#对象引用与回收" class="anchor-link heading2"><div>对象引用与回收</div></a></li><li class="anchor"><a href="/interview/jvm/gc/#有哪几种引用类型" class="anchor-link heading3"><div>有哪几种引用类型？</div></a></li><li class="anchor"><a href="/interview/jvm/gc/#如何判断对象是否可被回收" class="anchor-link heading3"><div>如何判断对象是否可被回收？</div></a></li><li class="anchor"><a href="/interview/jvm/gc/#什么是引用计数算法" class="anchor-link heading3"><div>什么是引用计数算法？</div></a></li><li class="anchor"><a href="/interview/jvm/gc/#什么是可达性分析算法" class="anchor-link heading3"><div>什么是可达性分析算法？</div></a></li><li class="anchor"><a href="/interview/jvm/gc/#如何判断一个类是否是无用的类" class="anchor-link heading3"><div>如何判断一个类是否是无用的类？</div></a></li><li class="anchor"><a href="/interview/jvm/gc/#内存分配与回收策略" class="anchor-link heading2"><div>内存分配与回收策略</div></a></li><li class="anchor"><a href="/interview/jvm/gc/#什么是-minor-gc-和-full-gc" class="anchor-link heading3"><div>什么是 Minor GC 和 Full GC？</div></a></li><li class="anchor"><a href="/interview/jvm/gc/#jvm-的内存分配策略是什么" class="anchor-link heading3"><div>JVM 的内存分配策略是什么？</div></a></li><li class="anchor"><a href="/interview/jvm/gc/#垃圾回收算法" class="anchor-link heading2"><div>垃圾回收算法</div></a></li><li class="anchor"><a href="/interview/jvm/gc/#什么是标记-清除算法" class="anchor-link heading3"><div>什么是标记-清除算法？</div></a></li><li class="anchor"><a href="/interview/jvm/gc/#什么是标记-整理算法" class="anchor-link heading3"><div>什么是标记-整理算法？</div></a></li><li class="anchor"><a href="/interview/jvm/gc/#什么是复制算法" class="anchor-link heading3"><div>什么是复制算法？</div></a></li><li class="anchor"><a href="/interview/jvm/gc/#什么是分代收集" class="anchor-link heading3"><div>什么是分代收集？</div></a></li><li class="anchor"><a href="/interview/jvm/gc/#垃圾回收器" class="anchor-link heading2"><div>垃圾回收器</div></a></li><li class="anchor"><a href="/interview/jvm/gc/#jvm-有哪些垃圾回收器" class="anchor-link heading3"><div>JVM 有哪些垃圾回收器？</div></a></li><li class="anchor"><a href="/interview/jvm/gc/#什么是-serial-收集器" class="anchor-link heading3"><div>什么是 Serial 收集器？</div></a></li><li class="anchor"><a href="/interview/jvm/gc/#什么是-parnew-收集器" class="anchor-link heading3"><div>什么是 ParNew 收集器？</div></a></li><li class="anchor"><a href="/interview/jvm/gc/#什么是-parallel-scavenge-收集器" class="anchor-link heading3"><div>什么是 Parallel Scavenge 收集器？</div></a></li><li class="anchor"><a href="/interview/jvm/gc/#什么是-cms-收集器" class="anchor-link heading3"><div>什么是 CMS 收集器？</div></a></li><li class="anchor"><a href="/interview/jvm/gc/#什么是-serial-old-收集器" class="anchor-link heading3"><div>什么是 Serial Old 收集器？</div></a></li><li class="anchor"><a href="/interview/jvm/gc/#什么是-parallel-old-收集器" class="anchor-link heading3"><div>什么是 Parallel Old 收集器？</div></a></li><li class="anchor"><a href="/interview/jvm/gc/#什么是-g1-收集器" class="anchor-link heading3"><div>什么是 G1 收集器？</div></a></li></ul></div></aside></div> <!----> <div class="content__content-top"></div> <div class="theme-default-content content__default"><h2 id="对象引用与回收"><a href="#对象引用与回收" class="header-anchor">#</a> 对象引用与回收</h2> <p>垃圾收集主要是针对堆和方法区进行的，程序计数器、虚拟机栈和本地方法栈这三个区域属于线程私有的，只存在于线程的生命周期内，线程结束之后就会消失，因此不需要对这三个区域进行垃圾回收。</p> <h3 id="有哪几种引用类型"><a href="#有哪几种引用类型" class="header-anchor">#</a> 有哪几种引用类型？</h3> <p>无论是通过引用计数算法判断对象的引用数量，还是通过可达性分析算法判断对象是否可达，判定对象是否可被回收都与引用有关。Java 提供了四种强度不同的引用类型，按照顺序引用强度逐渐降低。</p> <h4 id="强引用"><a href="#强引用" class="header-anchor">#</a> <strong>强引用</strong></h4> <p>被强引用关联的对象不会被回收，使用 <code>new</code> 关键字创建一个新对象时，就是创建了强引用。</p> <h4 id="软引用"><a href="#软引用" class="header-anchor">#</a> <strong>软引用</strong></h4> <p>被软引用关联的对象只有在内存不够的情况下才会被回收，使用 <code>SoftReference</code> 类来创建软引用。</p> <h4 id="弱引用"><a href="#弱引用" class="header-anchor">#</a> <strong>弱引用</strong></h4> <p>被弱引用关联的对象一定会被回收，也就是说它只能存活到下一次垃圾回收发生之前，使用 <code>WeakReference</code> 类来创建弱引用。</p> <h4 id="虚引用"><a href="#虚引用" class="header-anchor">#</a> <strong>虚引用</strong></h4> <p>又称为幽灵引用或者幻影引用，一个对象是否有虚引用的存在，不会对其生存时间造成影响，也无法通过虚引用得到一个对象。为一个对象设置虚引用的唯一目的是能在这个对象被回收时收到一个系统通知，需要和引用队列搭配起来使用，使用 <code>PhantomReference</code> 来创建虚引用。</p> <h3 id="如何判断对象是否可被回收"><a href="#如何判断对象是否可被回收" class="header-anchor">#</a> 如何判断对象是否可被回收？</h3> <p>可以使用引用计数法或者可达性分析算法来判断对象是否可被回收。</p> <h3 id="什么是引用计数算法"><a href="#什么是引用计数算法" class="header-anchor">#</a> 什么是引用计数算法？</h3> <p>为对象添加一个引用计数器，当对象增加一个引用时计数器加 1，引用失效时计数器减 1，引用计数为 0 的对象表示可被回收。在两个对象出现循环引用的情况下，此时引用计数器永远不为 0，导致无法对它们进行回收。正是因为循环引用的存在，因此 Java 虚拟机不使用引用计数算法。示例代码如下：</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Test</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token class-name">Object</span> instance <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>

    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">Test</span> a <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Test</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">Test</span> b <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Test</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        a<span class="token punctuation">.</span>instance <span class="token operator">=</span> b<span class="token punctuation">;</span>
        b<span class="token punctuation">.</span>instance <span class="token operator">=</span> a<span class="token punctuation">;</span>
        a <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
        b <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
        <span class="token function">doSomething</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><h3 id="什么是可达性分析算法"><a href="#什么是可达性分析算法" class="header-anchor">#</a> 什么是可达性分析算法？</h3> <p>以 GC Roots 为起始点进行搜索，节点所走过的路径称为引用链，当一个对象到 GC Roots 没有任何引用链相连的话，则证明此对象是不可用的。GC Roots 一般是以下内容：</p> <ul><li>虚拟机栈中局部变量表中引用的对象</li> <li>本地方法栈中 JNI 中引用的对象</li> <li>方法区中类静态属性引用的对象</li> <li>方法区中的常量引用的对象</li></ul> <div class="custom-block center"><p><img src="https://i.loli.net/2021/07/30/GpvU2nIrS4CjtD1.png" alt="GC Root.jpg"></p></div> <div class="custom-block danger"><p class="custom-block-title">不要使用 finalize() 方法</p> <p>对象在被回收时，会调用 <code>Object</code> 类中的 <code>finalize()</code> 方法，如果调用该方法的时候能够重新使对象重新被引用，就可以实现自救，但自救的机会只有一次。</p> <p><strong>如无特殊情况不用使用这个方法。</strong></p></div> <h3 id="如何判断一个类是否是无用的类"><a href="#如何判断一个类是否是无用的类" class="header-anchor">#</a> 如何判断一个类是否是无用的类？</h3> <p>类需要同时满足下面 3 个条件才能算是无用的类：</p> <ul><li>该类所有的实例都已经被回收，也就是 Java 堆中不存在该类的任何实例</li> <li>加载该类的 <code>ClassLoader</code> 已经被回收</li> <li>该类对应的 <code>java.lang.Class</code> 对象没有在任何地方被引用，无法在任何地方通过反射访问该类的方法</li></ul> <p>虚拟机可以对满足上述 3 个条件的无用类进行回收，这里说的仅仅是<strong>可以</strong>，而并不是和对象一样不使用了就会必然被回收。</p> <h2 id="内存分配与回收策略"><a href="#内存分配与回收策略" class="header-anchor">#</a> 内存分配与回收策略</h2> <h3 id="什么是-minor-gc-和-full-gc"><a href="#什么是-minor-gc-和-full-gc" class="header-anchor">#</a> 什么是 Minor GC 和 Full GC？</h3> <h4 id="minor-gc"><a href="#minor-gc" class="header-anchor">#</a> <strong>Minor GC</strong></h4> <p>回收新生代，因为新生代对象存活时间很短，因此 Minor GC 会频繁执行，执行的速度一般也会比较快。当 Eden 空间满时就会触发 Minor GC。</p> <h4 id="full-gc"><a href="#full-gc" class="header-anchor">#</a> <strong>Full GC</strong></h4> <p>回收新生代和老年代，老年代对象其存活时间长，因此 Full GC 很少执行，执行速度会比 Minor GC 慢很多。</p> <p>Full GC 的触发条件：</p> <ol><li>调用 <code>System.gc()</code></li></ol> <p>只是建议虚拟机执行 Full GC，但是虚拟机不一定真正去执行。不建议使用这种方式，而是让虚拟机管理内存。</p> <ol start="2"><li>老年代空间不足</li></ol> <p>老年代空间不足的常见场景为大对象直接进入老年代、长期存活的对象进入老年代等。为了避免以上原因引起的 Full GC，应当尽量不要创建过大的对象以及数组。除此之外，可以通过 <code>-Xmn</code> 参数调大新生代的大小，让对象尽量在新生代被回收掉，不进入老年代。还可以通过 <code>-XX:MaxTenuringThreshold</code> 调大对象进入老年代的年龄，让对象在新生代多存活一段时间。</p> <ol start="3"><li>空间分配担保失败</li></ol> <p>使用复制算法的 Minor GC 需要老年代的内存空间作担保，如果担保失败会执行一次 Full GC。</p> <ol start="4"><li>JDK1.7 及以前的永久代空间不足</li></ol> <p>在 JDK 1.7 及以前，HotSpot 虚拟机中的方法区是用永久代实现的，永久代中存放的为一些 Class 的信息、常量、静态变量等数据。当系统中要加载的类、反射的类和调用的方法较多时，永久代可能会被占满，在未配置为采用 CMS GC 的情况下也会执行 Full GC。如果经过 Full GC 仍然回收不了，那么虚拟机会抛出 <code>java.lang.OutOfMemoryError</code>。为避免以上原因引起的 Full GC，可采用的方法为：增大永久代空间大小或转为使用 CMS GC。</p> <ol start="5"><li>Concurrent Mode Failure</li></ol> <p>执行 CMS GC 的过程中同时有对象要放入老年代，而此时老年代空间不足（可能是 GC 过程中浮动垃圾过多导致暂时性的空间不足），便会报 Concurrent Mode Failure 错误，并触发 Full GC。</p> <h3 id="jvm-的内存分配策略是什么"><a href="#jvm-的内存分配策略是什么" class="header-anchor">#</a> JVM 的内存分配策略是什么？</h3> <h4 id="对象优先在-eden-上分配"><a href="#对象优先在-eden-上分配" class="header-anchor">#</a> <strong>对象优先在 Eden 上分配</strong></h4> <p>大多数情况下，对象在新生代 Eden 上分配，当 Eden 空间不够时，发起 Minor GC。</p> <h4 id="大对象直接进入老年代"><a href="#大对象直接进入老年代" class="header-anchor">#</a> <strong>大对象直接进入老年代</strong></h4> <p>大对象是指需要连续内存空间的对象，最典型的大对象是那种很长的字符串以及数组。经常出现大对象会提前触发垃圾收集以获取足够的连续空间分配给大对象。<code>-XX:PretenureSizeThreshold</code> 大于此参数值的对象直接在老年代分配，避免在 Eden 和 Survivor 之间的大量内存复制。</p> <h4 id="长期存活的对象进入老年代"><a href="#长期存活的对象进入老年代" class="header-anchor">#</a> <strong>长期存活的对象进入老年代</strong></h4> <p>为对象定义年龄计数器，对象在 Eden 出生并经过 Minor GC 依然存活，将移动到 Survivor 中，年龄就增加 1 岁，增加到一定年龄则移动到老年代中。参数 <code>-XX:MaxTenuringThreshold</code> 用来定义年龄的阈值。</p> <h4 id="动态对象年龄判定"><a href="#动态对象年龄判定" class="header-anchor">#</a> <strong>动态对象年龄判定</strong></h4> <p>虚拟机并不是永远要求对象的年龄必须达到 <code>MaxTenuringThreshold</code> 才能晋升老年代，如果在 Survivor 中相同年龄所有对象大小的总和大于 Survivor 空间的一半，则年龄大于或等于该年龄的对象可以直接进入老年代，无需等到 <code>MaxTenuringThreshold</code> 中要求的年龄。</p> <h4 id="空间分配担保"><a href="#空间分配担保" class="header-anchor">#</a> <strong>空间分配担保</strong></h4> <p>在发生 Minor GC 之前，虚拟机先检查老年代最大可用的连续空间是否大于新生代所有对象总空间，如果条件成立的话，那么 Minor GC 可以确认是安全的。如果不成立的话虚拟机会查看 <code>HandlePromotionFailure</code> 的值是否允许担保失败，如果允许那么就会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小，如果大于将会尝试着进行一次 Minor GC；如果小于或者 <code>HandlePromotionFailure</code> 的值不允许冒险，那么就要进行一次 Full GC。</p> <h2 id="垃圾回收算法"><a href="#垃圾回收算法" class="header-anchor">#</a> 垃圾回收算法<span class="badge error" style="vertical-align:top;" data-v-7b453e57>重点</span></h2> <h3 id="什么是标记-清除算法"><a href="#什么是标记-清除算法" class="header-anchor">#</a> 什么是标记-清除算法？</h3> <p>该算法分为“标记”和“清除”阶段：首先标记出所有不需要回收的对象，在标记完成后统一回收掉所有没有被标记的对象。它是最基础的收集算法，后续的算法都是针对它的不足进行改进得到的。这种垃圾收集算法会带来两个明显的问题：</p> <ul><li>效率问题</li> <li>空间问题（标记清除后会产生大量不连续的碎片）</li></ul> <div class="custom-block center"><p><img src="https://i.loli.net/2021/07/30/SPvYVlhOpmgKwnJ.png" alt="标记-清理.jpg"></p></div> <h3 id="什么是标记-整理算法"><a href="#什么是标记-整理算法" class="header-anchor">#</a> 什么是标记-整理算法？</h3> <p>让所有存活的对象都向一端移动，然后直接清理掉端边界以外的内存。相比较标记-清除算法而言，它不会产生内存碎片，但是需要移动大量对象，处理效率低。</p> <div class="custom-block center"><p><img src="https://i.loli.net/2021/07/30/rK5dXPjukpSx4Hc.png" alt="标记-整理.jpg"></p></div> <h3 id="什么是复制算法"><a href="#什么是复制算法" class="header-anchor">#</a> 什么是复制算法？</h3> <p>将内存划分为大小相等的两块，每次只使用其中一块，当这一块内存用完了就将还存活的对象复制到另一块上面，然后再把使用过的内存空间进行一次清理。 主要不足是只使用了内存的一半。</p> <p>现在的商业虚拟机都采用这种收集算法回收新生代，但是并不是划分为大小相等的两块，而是一块较大的 Eden 空间和两块较小的 Survivor 空间，每次使用 Eden 和其中一块 Survivor。在回收时，将 Eden 和 Survivor 中还存活着的对象全部复制到另一块 Survivor 上，最后清理 Eden 和使用过的那一块 Survivor。</p> <p>HotSpot 虚拟机的 Eden 和 Survivor 大小比例默认为 8:1，保证了内存的利用率达到 90%。如果每次回收有多于 10% 的对象存活，那么一块 Survivor 就不够用了，此时需要依赖于老年代进行空间分配担保，也就是借用老年代的空间存储放不下的对象。</p> <div class="custom-block center"><p><img src="https://i.loli.net/2021/07/30/PGaUAmF2Txfq5Ss.png" alt="复制.jpg"></p></div> <h3 id="什么是分代收集"><a href="#什么是分代收集" class="header-anchor">#</a> 什么是分代收集？</h3> <p>现在的商业虚拟机采用分代收集算法，它根据对象存活周期将内存划分为几块，不同块采用适当的收集算法，一般将堆分为新生代和老年代：</p> <ul><li>新生代使用复制算法</li> <li>老年代使用标记-清除或者标记-整理算法</li></ul> <h2 id="垃圾回收器"><a href="#垃圾回收器" class="header-anchor">#</a> 垃圾回收器</h2> <h3 id="jvm-有哪些垃圾回收器"><a href="#jvm-有哪些垃圾回收器" class="header-anchor">#</a> JVM 有哪些垃圾回收器？</h3> <div class="custom-block center"><p><img src="https://i.loli.net/2021/07/30/zQd3n6VFievBKtY.png" alt="垃圾回收器.jpg"></p></div> <p>以上是 HotSpot 虚拟机中的 7 个垃圾收集器，连线表示垃圾收集器可以配合使用。</p> <h4 id="单线程与多线程"><a href="#单线程与多线程" class="header-anchor">#</a> <strong>单线程与多线程</strong></h4> <p>单线程指的是垃圾收集器只使用一个线程进行回收，多线程指的是垃圾收集器使用多个线程进行回收。</p> <h4 id="串行与并行"><a href="#串行与并行" class="header-anchor">#</a> <strong>串行与并行</strong></h4> <p>串行指的是垃圾收集器与用户程序交替执行，这意味着在执行垃圾收集的时候需要停顿用户程序；并行指的是垃圾收集器和用户程序同时执行，除了 CMS 和 G1 之外，其它垃圾收集器都是以串行的方式执行。</p> <h3 id="什么是-serial-收集器"><a href="#什么是-serial-收集器" class="header-anchor">#</a> 什么是 Serial 收集器？</h3> <p>Serial（串行）收集器是最基本、历史最悠久的垃圾收集器了。看名字就知道这个收集器是一个单线程收集器，它的单线程的意义不仅仅意味着它只会使用一条垃圾收集线程去完成垃圾收集工作，更重要的是它在进行垃圾收集工作的时候必须暂停其他所有的工作线程（&quot;Stop The World&quot;），直到它收集结束。</p> <p>Serial 收集器在新生代采用复制算法，在老年代采用标记-整理算法。</p> <div class="custom-block center"><p><img src="https://i.loli.net/2021/07/30/fmjrMaopxuhbAIQ.png" alt="Serial收集器.jpg"></p></div> <h3 id="什么是-parnew-收集器"><a href="#什么是-parnew-收集器" class="header-anchor">#</a> 什么是 ParNew 收集器？</h3> <p>ParNew 是 Serial 的多线程版本，除了使用多线程以外，与 Serial 收集器完全一致。</p> <div class="custom-block center"><p><img src="https://i.loli.net/2021/07/30/Tzb4P7dEcjXQuGO.png" alt="ParNew收集器.jpg"></p></div> <h3 id="什么是-parallel-scavenge-收集器"><a href="#什么是-parallel-scavenge-收集器" class="header-anchor">#</a> 什么是 Parallel Scavenge 收集器？</h3> <p>Parallel Scavenge 收集器关注点是吞吐量（高效率的利用 CPU）。CMS 等垃圾收集器的关注点更多的是用户线程的停顿时间（提高用户体验）。</p> <p>所谓吞吐量就是 CPU 中用于运行用户代码的时间与 CPU 总消耗时间的比值。Parallel Scavenge 收集器提供了很多参数供用户找到最合适的停顿时间或最大吞吐量，如果对于收集器运作不太了解，手工优化存在困难的时候，使用 Parallel Scavenge 收集器配合自适应调节策略，把内存管理优化交给虚拟机去完成就可以了。</p> <p>新生代采用复制算法，老年代采用标记-整理算法，是一个多线程的收集器。同时它是 JDK8 的默认收集器。</p> <div class="custom-block center"><p><img src="https://i.loli.net/2021/07/30/Tzb4P7dEcjXQuGO.png" alt="ParallelScavenge收集器.jpg"></p></div> <h3 id="什么是-cms-收集器"><a href="#什么是-cms-收集器" class="header-anchor">#</a> 什么是 CMS 收集器？<span class="badge error" style="vertical-align:top;" data-v-7b453e57>重点</span></h3> <p>CMS（Concurrent Mark Sweep）收集器是一种以获取最短回收停顿时间为目标的收集器，它非常适合在注重用户体验的应用上使用。它是 HotSpot 虚拟机第一款真正意义上的并发收集器，第一次实现了让垃圾收集线程与用户线程（基本上）同时工作。</p> <p>从名字中的 Mark Sweep 这两个词可以看出，CMS 收集器是使用“标记-清除”算法实现的，它的运作过程相比于前面几种垃圾收集器来说更加复杂一些。整体分为四个步骤：</p> <h4 id="初始标记"><a href="#初始标记" class="header-anchor">#</a> <strong>初始标记</strong></h4> <p>暂停所有的其他线程，并记录下直接与 root 相连的对象，速度很快。</p> <h4 id="并发标记"><a href="#并发标记" class="header-anchor">#</a> <strong>并发标记</strong></h4> <p>同时开启 GC 和用户线程，用一个闭包结构去记录可达对象。但在这个阶段结束，这个闭包结构并不能保证包含当前所有的可达对象。因为用户线程可能会不断的更新引用域，所以 GC 线程无法保证可达性分析的实时性。所以这个算法里会跟踪记录这些发生引用更新的地方。</p> <h4 id="重新标记"><a href="#重新标记" class="header-anchor">#</a> <strong>重新标记</strong></h4> <p>重新标记阶段就是为了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录，这个阶段的停顿时间一般会比初始标记阶段的时间稍长，远远比并发标记阶段时间短。</p> <h4 id="并发清除"><a href="#并发清除" class="header-anchor">#</a> <strong>并发清除</strong></h4> <p>开启用户线程，同时 GC 线程开始对未标记的区域做清扫。</p> <div class="custom-block center"><p><img src="https://i.loli.net/2021/07/30/cIWHRtZV2boTdL7.png" alt="CMS收集器.jpg"></p></div> <p>CMS 收集器的缺点是：</p> <h4 id="吞吐量低"><a href="#吞吐量低" class="header-anchor">#</a> <strong>吞吐量低</strong></h4> <p>低停顿时间是以牺牲吞吐量为代价的。</p> <h4 id="无法处理浮动垃圾"><a href="#无法处理浮动垃圾" class="header-anchor">#</a> <strong>无法处理浮动垃圾</strong></h4> <p>可能出现 Concurrent Mode Failure。浮动垃圾是指并发清除阶段由于用户线程继续运行而产生的垃圾，这部分垃圾只能到下一次 GC 时才能进行回收。由于浮动垃圾的存在，因此需要预留出一部分内存，意味着 CMS 收集不能像其它收集器那样等待老年代快满的时候再回收。如果预留的内存不够存放浮动垃圾，就会出现 Concurrent Mode Failure，这时虚拟机将临时启用 Serial Old 来替代 CMS。</p> <h4 id="标记-清除算法导致的空间碎片"><a href="#标记-清除算法导致的空间碎片" class="header-anchor">#</a> <strong>标记 - 清除算法导致的空间碎片</strong></h4> <p>“标记-清除”算法会导致收集结束时会有大量空间碎片产生。</p> <h3 id="什么是-serial-old-收集器"><a href="#什么是-serial-old-收集器" class="header-anchor">#</a> 什么是 Serial Old 收集器？</h3> <p>Serial 收集器的老年代版本，它同样是一个单线程收集器。它主要有两大用途：</p> <ul><li>在 JDK1.5 以及以前的版本中与 Parallel Scavenge 收集器搭配使用</li> <li>作为 CMS 收集器的后备方案，在并发收集发生 Concurrent Mode Failure 时使用</li></ul> <h3 id="什么是-parallel-old-收集器"><a href="#什么是-parallel-old-收集器" class="header-anchor">#</a> 什么是 Parallel Old 收集器？</h3> <p>Parallel Scavenge 收集器的老年代版本，在注重吞吐量以及 CPU 资源敏感的场合，都可以优先考虑 Parallel Scavenge 加 Parallel Old 收集器。</p> <h3 id="什么是-g1-收集器"><a href="#什么是-g1-收集器" class="header-anchor">#</a> 什么是 G1 收集器？<span class="badge error" style="vertical-align:top;" data-v-7b453e57>重点</span></h3> <p>G1 (Garbage-First) 是一款面向服务器的垃圾收集器，主要针对配备多颗处理器及大容量内存的机器。以极高概率满足 GC 停顿时间要求的同时，还具备高吞吐量性能特征。G1 把堆划分成多个大小相等的独立区域（Region），使新生代和老年代不再物理隔离。</p> <div class="custom-block center"><p><img src="https://i.loli.net/2021/07/30/JvebfMrtipYwz8P.png" alt="G1Region.jpg"></p></div> <p>通过引入 Region 的概念，将原来的一整块内存空间划分成多个的小空间，使得每个小空间可以单独进行垃圾回收。这种划分方法带来了很大的灵活性，使得可预测的停顿时间模型成为可能。通过记录每个 Region 垃圾回收时间以及回收所获得的空间（这两个值是通过过去回收的经验获得），并维护一个优先列表，每次根据允许的收集时间，优先回收价值最大的 Region。</p> <p>每个 Region 都有一个 Remembered Set，用来记录该 Region 对象的引用对象所在的 Region。通过使用 Remembered Set，在做可达性分析的时候就可以避免全堆扫描。</p> <p>如果不计算维护 Remembered Set 的操作，G1 收集器的运作大致可划分为以下几个步骤：</p> <ol><li><p>初始标记</p></li> <li><p>并发标记</p></li> <li><p>最终标记</p></li></ol> <p>为了修正在并发标记期间因用户程序继续运作而导致标记产生变动的那一部分标记记录，虚拟机将这段时间对象变化记录在线程的 Remembered Set Logs 里面，最终标记阶段需要把 Remembered Set Logs 的数据合并到 Remembered Set 中。这阶段需要停顿线程，但是可并行执行。</p> <ol start="4"><li>筛选回收</li></ol> <p>首先对各个 Region 中的回收价值和成本进行排序，根据用户所期望的 GC 停顿时间来制定回收计划。此阶段其实也可以做到与用户程序一起并发执行，但是因为只回收一部分 Region，时间是用户可控制的，而且停顿用户线程将大幅度提高收集效率。</p> <p>G1 收集器的流程图如下：</p> <div class="custom-block center"><p><img src="https://i.loli.net/2021/07/30/atSL548mrYAlR1T.png" alt="G1垃圾回收器.jpg"></p></div> <p>总结一下 G1 收集器的特点：</p> <ul><li>并行与并发</li></ul> <p>G1 能充分利用 CPU、多核环境下的硬件优势，使用多个 CPU（CPU 或者 CPU 核心）来缩短 Stop-The-World 的停顿时间。部分其他收集器原本需要停顿 Java 线程执行的 GC 动作，G1 收集器仍然可以通过并发的方式让 java 程序继续执行。</p> <ul><li>分代收集</li></ul> <p>虽然 G1 可以不需要其他收集器配合就能独立管理整个 GC 堆，但是还是保留了分代的概念。</p> <ul><li>空间整合</li></ul> <p>与 CMS 的“标记--清理”算法不同，G1 从整体来看是基于“标记整理”算法实现的收集器，从局部上来看是基于“复制”算法实现的。</p> <ul><li>可预测的停顿</li></ul> <p>这是 G1 相对于 CMS 的另一个大优势，降低停顿时间是 G1 和 CMS 共同的关注点，但 G1 除了追求低停顿外，还能建立可预测的停顿时间模型，能让使用者明确指定在一个长度为 M 毫秒的时间片段内。</p></div> <!----> <div class="content__content-bottom"></div> <footer class="page-meta"><div class="edit-link"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="icon edit-icon"><path d="M117.953 696.992 64.306 959.696l265.931-49.336 450.204-452.505-212.284-213.376-450.204 452.513zm496.384-296.326L219.039 797.993l-46.108-46.34L568.233 354.33l46.104 46.335zm345.357-122.99-114.45 115.04-212.288-213.377 114.45-115.035 212.288 213.371zm0 0" fill="currentColor"></path></svg> <a href="https://github.com/lxy1152/lxy1152.github.io/edit/main/interview/jvm/gc.md" target="_blank" rel="noopener noreferrer">编辑此页</a></div> <div class="meta-item update-time"><span class="label">上次编辑于:</span> <span class="info">2021年8月1日 19:23</span></div> <div class="meta-item contributors"><span class="label">贡献者: </span> <span class="info"><span title="email: 2676092082@qq.com" class="contributor">
          Xiangyu Li
        </span> <!----></span></div></footer> <div class="page-nav"><p class="inner"><span class="prev"><a href="/interview/jvm/classloader/" class="prev"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="icon prev-icon"><path d="M906.783 588.79c-.02 8.499-6.882 15.36-15.38 15.37l-443.7-.01 75.704 191.682c2.52 6.42.482 13.763-5.038 17.91-5.52 4.168-13.138 4.147-18.616-.092L123.228 524.175a15.362 15.362 0 0 1-6-12.165c0-4.782 2.222-9.277 6-12.185L499.753 210.35a15.388 15.388 0 0 1 9.38-3.195c3.236 0 6.502 1.034 9.236 3.103 5.52 4.147 7.578 11.49 5.038 17.91L447.683 419.84l443.72-.01c8.498.01 15.36 6.881 15.36 15.36l.02 153.6z" fill="currentColor"></path></svg>
        ☀️ 类加载机制
      </a></span> <span class="next"><a href="/interview/framework/">
        🌀 框架使用 - 简介
        <svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="icon next-icon"><path d="M906.772 512c0 4.772-2.211 9.267-5.99 12.175L524.257 813.66a15.37 15.37 0 0 1-18.616.092 15.368 15.368 0 0 1-5.038-17.91l75.714-191.672h-443.73c-8.488 0-15.36-6.881-15.36-15.36v-153.6c0-8.489 6.872-15.36 15.36-15.36h443.73l-75.714-191.682a15.358 15.358 0 0 1 5.048-17.91c5.51-4.158 13.128-4.137 18.606.092l376.525 289.485a15.323 15.323 0 0 1 5.99 12.165z" fill="currentColor"></path></svg></a></span></p></div> <div class="comments-wrapper"><div class="waline-wrapper"><div id="waline-comment"></div></div></div> <!----> <div class="content__page-bottom"></div></main> <footer class="footer-wrapper"><!----> <!----> <div class="copyright">Copyright © 2021 Xiangyu Li</div></footer></div><div class="global-ui"><!----><div tabindex="-1" role="dialog" aria-hidden="true" class="pswp"><div class="pswp__bg"></div> <div class="pswp__scroll-wrap"><div class="pswp__container"><div class="pswp__item"></div> <div class="pswp__item"></div> <div class="pswp__item"></div></div> <div class="pswp__ui pswp__ui--hidden"><div class="pswp__top-bar"><div class="pswp__counter"></div> <button class="pswp__button pswp__button--close"></button> <button class="pswp__button pswp__button--share"></button> <button class="pswp__button pswp__button--fs"></button> <button class="pswp__button pswp__button--zoom"></button> <div class="pswp__preloader"><div class="pswp__preloader__icn"><div class="pswp__preloader__cut"><div class="pswp__preloader__donut"></div></div></div></div></div> <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap"><div class="pswp__share-tooltip"></div></div> <button class="pswp__button pswp__button--arrow--left"></button> <button class="pswp__button pswp__button--arrow--right"></button> <div class="pswp__caption"><div class="pswp__caption__center"></div></div></div></div></div></div></div>
    <script src="/assets/js/app.a42375e9.js" defer></script><script src="/assets/js/vendors~layout-Layout.8269724e.js" defer></script><script src="/assets/js/vendors~layout-Blog~layout-Layout~layout-NotFound.43b0f70d.js" defer></script><script src="/assets/js/page-🌙垃圾回收机制.db23d79a.js" defer></script><script src="/assets/js/vendors~layout-Blog~layout-Layout~layout-NotFound~layout-Slide.99c28334.js" defer></script>
  </body>
</html>
